package com.xuecheng.content.service.jobHandler;

import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.feignclient.SearchServiceClient;
import com.xuecheng.content.model.po.CourseIndex;
import com.xuecheng.content.model.po.CoursePublish;
import com.xuecheng.content.service.CoursePublishService;
import com.xuecheng.messagesdk.model.po.MqMessage;
import com.xuecheng.messagesdk.service.MessageProcessAbstract;
import com.xuecheng.messagesdk.service.MqMessageService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.concurrent.TimeUnit;


/**
 * 课程发布任务类
 */

@Slf4j
@Component
public class CoursePublishTask extends MessageProcessAbstract {

    @Autowired
    private CoursePublishService coursePublishService;
    @Autowired
    private SearchServiceClient searchServiceClient;

    //任务调度入口
    @XxlJob("CoursePublishJobHandler")
    public void coursePublishJobHandler() throws Exception {
        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        log.debug("shardIndex="+shardIndex+",shardTotal="+shardTotal);
        //参数:分片序号、分片总数、消息类型、一次最多取到的任务数量、一次任务调度执行的超时时间
        process(shardIndex,shardTotal,"course_publish",30,60);
    }




    //课程发布任务处理
    @Override
    public boolean execute(MqMessage mqMessage) {

        //从形参中拿课程id
       Long courseId = Long.valueOf(mqMessage.getBusinessKey1());

        //向elasticsearch写索引数据
        saveCourseIndex(mqMessage,courseId);

        //课程静态化上传到minio
        generateCourseHtml(mqMessage,courseId);

        //向redis写缓存
        saveCourseCache(mqMessage,courseId);

        //返回true表示任务完成
        return true;

    }

    /**
     * 课程索引----第二个阶段的任务
     * @param mqMessage
     * @param courseId
     */
    private void saveCourseIndex(MqMessage mqMessage, Long courseId) {

        //任务id
        Long id = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        int stageTwo = mqMessageService.getStageTwo(id);

        //幂等性判断
        if (stageTwo>0){
            log.debug("课程索引已处理直接返回，课程id:{}",courseId);
            return ;
        }

        log.debug("保存课程索引信息,课程id:{}",courseId);

        //拿到课程发布信息
        CoursePublish coursePublish = coursePublishService.getById(courseId);
        //拷贝至课程索引对象
        CourseIndex courseIndex = new CourseIndex();
        BeanUtils.copyProperties(coursePublish,courseIndex);
        //远程调用搜索服务api添加课程信息到索引
        Boolean add = searchServiceClient.add(courseIndex);
        if (!add){
            XueChengPlusException.cast("添加索引失败");
        }

        //保存第一阶段状态
        mqMessageService.completedStageTwo(id);
    }


    /**
     * 上传静态化页面---第一个阶段的任务
     * @param mqMessage
     * @param courseId
     */
    private void generateCourseHtml(MqMessage mqMessage, Long courseId) {

        Long id = mqMessage.getId();
        log.debug("开始进行课程静态化,课程id:{}",courseId);
        //做幂等性处理
        MqMessageService mqMessageService = this.getMqMessageService();
        int stageOne = mqMessageService.getStageOne(id);
        if (stageOne>0){
            log.debug("课程静态化已处理直接返回，课程id:{}",courseId);
            return ;
        }
//        try {
//            TimeUnit.SECONDS.sleep(10);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
        //生成静态化页面
        File file = coursePublishService.generateCourseHtml(courseId);
        //上传静态化页面
        if (file!=null){
            coursePublishService.uploadCourseHtml(courseId,file);
        }
        //保存第一阶段状态
        mqMessageService.completedStageOne(id);
    }


    /**
     * 课程缓存----第三阶段的任务
     * @param mqMessage
     * @param courseId
     */
    private void saveCourseCache(MqMessage mqMessage, Long courseId) {

        log.debug("保存课程索引信息,课程id:{}",courseId);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


}
